#include <iostream>
#include "WatchDog.h"
#include "../config/Config.h"
#include "../logs/LogStream.h"
#include "../config/ConfigDbReader.h"
#include <signal.h>

using namespace kc_sf;

// --------------------------------------------------------- //

WatchDog & WatchDog::getInstance( bool configuration_from_xml )
{
	static WatchDog instance( configuration_from_xml );
	return instance;
}

// --------------------------------------------------------- //

WatchDog::WatchDog( bool configuration_from_xml )
{
	// odpalenie systemu
	std::cout << "System kc_smtp rozpoczyna działanie. Witam!" << std::endl;

	// zainicjalizowanie konfiguracji
	Config &cfg = Config::getInstance();

	// TODO
	//if( configuration_from_xml )
		//ConfigReader...
	ConfigDbReader db_reader;
	db_reader();
    std::cout << "Wczytano opcje konfiguracyjne. " << std::endl;
    size_t rules_nr = cfg.cRules.size();
    switch( rules_nr )
    {
    	case 1:
    	    std::cout << "Wczytano 1 definicję reguły" << std::endl;
    	    break;
    	case 2:
    	case 3:
    	case 4:
		    std::cout << "Wczytano " << rules_nr << " definicje reguł" << std::endl;
		    break;
		case 0:
		default:
		    std::cout << "Wczytano " << rules_nr << " definicji reguł" << std::endl;
		    break;
    }

    LogStream::getInstance( cfg.cLogsFilepath, false );
    wd_logger = new Logger();
    if( wd_logger->isOpened() )
    	std::cout << "Otwarto plik dziennika zdarzeń" << std::endl;
    else
    {
    	std::cerr << "Błąd dostępu do pliku dziennika zdarzeń" << std::endl;
    	return;
    }

    *wd_logger << info << watchdog << "Start systemu" << flush;

	// watki-nadzorcy
	boost::thread *system_status_thread = new boost::thread( &WatchDog::startSystemStatus, this );
	wd_threads.add_thread( system_status_thread );

	boost::thread *listener_thread = new boost::thread( &WatchDog::startListener, this );
	wd_threads.add_thread( listener_thread );

	boost::thread *analyzer_thread = new boost::thread( &WatchDog::startAnalyzer, this );
	wd_threads.add_thread( analyzer_thread );

	boost::thread *sender_thread = new boost::thread( &WatchDog::startOutputSender, this );
	wd_threads.add_thread( sender_thread );

	wd_threads.join_all();
}

// --------------------------------------------------------- //

WatchDog::~WatchDog()
{
	wd_threads.interrupt_all();
	if( wd_analyzer )
		delete wd_analyzer;
	if( wd_listener )
		delete wd_listener;
	if( wd_sender )
		delete wd_sender;

	*wd_logger << info << watchdog << "Koniec pracy systemu" << flush;
	delete wd_logger;

	wd_threads.join_all();
}

// --------------------------------------------------------- //

void WatchDog::stop()
{
	std::cout << "STOP" << std::endl;
	WatchDog::getInstance().wd_listener->stop();
	WatchDog::getInstance().wd_sender->stop();
	WatchDog::getInstance().wd_threads.interrupt_all();
}

// --------------------------------------------------------- //

void WatchDog::startListener()
{
	// block signals
    sigset_t signal_set;
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGPIPE); // http://www.unixguide.net/network/socketfaq/2.19.shtml
    pthread_sigmask(SIG_BLOCK, &signal_set, NULL);

	wd_listener = new Listener();
	wd_listener->start();
}

// --------------------------------------------------------- //

void WatchDog::startAnalyzer()
{
	// block signals
    sigset_t signal_set;
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGPIPE); // http://www.unixguide.net/network/socketfaq/2.19.shtml
    pthread_sigmask(SIG_BLOCK, &signal_set, NULL);

	wd_analyzer = new Analyzer();
	wd_analyzer->start();
}

// --------------------------------------------------------- //

void WatchDog::startOutputSender()
{
	// block signals
    sigset_t signal_set;
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGPIPE); // http://www.unixguide.net/network/socketfaq/2.19.shtml
    pthread_sigmask(SIG_BLOCK, &signal_set, NULL);

    wd_sender = new OutputSender();
	wd_sender->start();
}

// --------------------------------------------------------- //

void WatchDog::startSystemStatus()
{
	// block signals
    sigset_t signal_set;
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGPIPE); // http://www.unixguide.net/network/socketfaq/2.19.shtml
    pthread_sigmask(SIG_BLOCK, &signal_set, NULL);

    wd_system_status = new SystemStatus();
    wd_system_status->start();
}

// --------------------------------------------------------- //

void WatchDog::startWWWService()
{
}
